﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace BlackStar
{
    public class ThemePartContentReader : ContentTypeReader<ThemePart>
    {
        protected override ThemePart Read(ContentReader input, ThemePart existingInstance)
        {
            ThemePart part = new ThemePart();
            part.ReadContent(input);
            return part;
        }
    }

    public class ThemePart
    {
        internal GUI myGui;

        public string AssetName;
        public Point MinimumSize = Point.Zero;

        [ContentSerializerIgnore]
        protected Texture2D texture;

        public Dictionary<string, Rectangle> Rectangles = new Dictionary<string, Rectangle>();
        public Dictionary<string, List<string>> PartLists = new Dictionary<string, List<string>>();

        public void Draw(string style, Rectangle[] dest, Color color)
        {
            if (PartLists.ContainsKey(style))
            {
                this.Draw(PartLists[style], dest, color);
            }
            else
            {
                this.Draw(PartLists["Default"], dest, color);
            }
        }

        protected void Draw(List<string> parts, Rectangle[] dest, Color color)
        {
            if (parts.Count != dest.Length)
            { throw new ApplicationException("The quantity of rectangles does not match the part list."); }

            for (int i = 0; i < dest.Length; i++)
            {
                myGui.batch.Draw(this.texture, dest[i], this.Rectangles[parts[i]], color);
            }
        }

        protected internal void ReadContent(ContentReader input)
        {
            AssetName = input.ReadString();
            Rectangles = input.ReadObject<Dictionary<string, Rectangle>>();
            PartLists = input.ReadObject<Dictionary<string, List<string>>>();
            MinimumSize = input.ReadObject<Point>();

            // check that their is a default part list.
            if (!PartLists.ContainsKey("Default"))
            { throw new ApplicationException("A Default PartList must be specified."); }
            // check that the part lists do not contain refrences to 
            // rectangles that do not exist.
            CheckPartLists();

            this.Load(input);
        }

        internal virtual void Load(ContentReader input)
        {
            string assetDir = input.AssetName.Substring(0, input.AssetName.LastIndexOf("\\") + 1);
            texture = input.ContentManager.Load<Texture2D>(assetDir + this.AssetName);
        }

        private void CheckPartLists()
        {
            foreach (KeyValuePair<string, List<string>> style in this.PartLists)
            {
                foreach (string key in style.Value)
                {
                    if (!Rectangles.ContainsKey(key))
                    {
                        throw new ApplicationException("The style '" + style.Key +
                             "' uses a rectangle with the key '" + key +
                             "' which is undefined.");
                    }
                }
            }
        }

        [ContentSerializerIgnore]
        public GUI GUI
        {
            get { return myGui; }
            set { myGui = value; }
        }
    }

    public class ThemeContentReader : ContentTypeReader<Theme>
    {
        protected override Theme Read(ContentReader input, Theme existingInstance)
        {

            Theme theme = new Theme();
            theme.ReadContent(input);
            return theme;
        }
    }

    public class Theme
    {
        internal GUI myGui;

        public CursorList Cursors = new CursorList();
        public FontList Fonts = new FontList();
        public ThemePart Form;
        public ThemePart Button;
        public ThemePart Textbox;

        [ContentSerializerIgnore]
        public Texture2D pixel;

        protected internal void ReadContent(ContentReader input)
        {
            Cursors = input.ReadObject<CursorList>();
            if (!Cursors.ContainsKey("Default")) throw new ApplicationException("A cursor named 'Default' must be defined.");

            Fonts = input.ReadObject<FontList>();
            Form = input.ReadObject<ThemePart>();
            Button = input.ReadObject<ThemePart>();
            Textbox = input.ReadObject<ThemePart>();
        }

        public Theme()
        {

        }

        public virtual void Load()
        {
            pixel = CreatePixelTexture(GUI.GraphicsDevice, 1, 1, Color.White);
        }

        protected Texture2D CreatePixelTexture(GraphicsDevice device, int width, int height, Color color)
        {
            RenderTarget2D LevelRenderTarget = new RenderTarget2D(device, width, height, 1,
                device.PresentationParameters.BackBufferFormat, device.PresentationParameters.MultiSampleType,
                device.PresentationParameters.MultiSampleQuality, RenderTargetUsage.PreserveContents);

            DepthStencilBuffer stencilBuffer = new DepthStencilBuffer(device, width, height,
                device.DepthStencilBuffer.Format, device.PresentationParameters.MultiSampleType,
                device.PresentationParameters.MultiSampleQuality);

            device.SetRenderTarget(0, LevelRenderTarget);

            // Cache the current depth buffer
            DepthStencilBuffer old = device.DepthStencilBuffer;
            // Set our custom depth buffer
            device.DepthStencilBuffer = stencilBuffer;

            device.Clear(color);

            device.SetRenderTarget(0, null);

            // Reset the depth buffer
            device.DepthStencilBuffer = old;
            return LevelRenderTarget.GetTexture();
        }

        [ContentSerializerIgnore]
        public GUI GUI
        {
            get { return myGui; }
            set
            {
                myGui = value;
                Fonts.GUI = value;
                Form.GUI = value;
                Button.GUI = value;
                Textbox.GUI = value;
            }
        }

        public virtual void Update(GameTime gameTime) { }
    }
}
